package org.smart4j.plugin.security.aspect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.smart4j.framework.annotation.Aspect;
import org.smart4j.framework.annotation.Controller;
import org.smart4j.framework.proxy.AspectProxy;
import org.smart4j.framework.util.CollectionUtil;
import org.smart4j.plugin.security.annotation.User;
import org.smart4j.plugin.security.exception.AuthcException;

/**
 * description: 实现授权的注解切面
 * @version v1.0
 * @author w
 * @date 2018年11月18日下午9:41:13
 **/
@Aspect(value = Controller.class)
public class AuthzAnnotationAspect extends AspectProxy {
	
	/**
	 * 定义一个基于授权功能的注解数组 
	 */
	private static final Class[] ANNOTATION_CLASS_ARRAY = {User.class};
	
	@Override
	protected void before(Class<?> targetClass, Method targetMethod, Object[] methodParams) {
		Annotation annotation = getAnnotation(targetClass, targetMethod);
		if(null != annotation){
			// 判断授权注解的类型
			Class<? extends Annotation> annotationType = annotation.annotationType();
			if(annotationType.equals(User.class)){
				handleUser();
			}
		}
	}
	
	@SuppressWarnings("unchecked")
	private Annotation getAnnotation(Class<?> clzz , Method method){
		for (Class<? extends Annotation> annotationClass : ANNOTATION_CLASS_ARRAY) {
			// 判断方法上是否有授权的注解 
			if(method.isAnnotationPresent(annotationClass)){
				return method.getAnnotation(annotationClass);
			}
			// 判断目标类上是否有授权的注解
			if(clzz.isAnnotationPresent(annotationClass)){
				return clzz.getAnnotation(annotationClass);
			}
		}
		// 若方法和目标类上都没有授权注解，则返回 null 
		return null;
	}
	
	private void handleUser() throws AuthcException {
		Subject currentUser = SecurityUtils.getSubject();
		PrincipalCollection principals = currentUser.getPrincipals();
		if(principals == null || principals.isEmpty()){
			throw new AuthcException("当前用户尚未登陆！");
		}
	}
}
